﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Markup;

namespace Corona
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public event EventHandler<Corona.TagPresent.SourceDragOnEventArgs> SourceDragOn;
        public Window1()
        {
            InitializeComponent();
        }
        private void EndSelect(object sender, MouseButtonEventArgs e)
        {
            //Storyboard hideSelect = this.FindResource("HideSelect") as Storyboard;
            
            //hideSelect.Begin();
            //hideSelect.Completed += hideSelectHiden;
            dselect.Visibility = Visibility.Hidden;
            IsDrawing = false;
        }
        private void OnSelecting(object sender, MouseEventArgs e)
        {
           // Line l = new Line();
            EndPoint = e.GetPosition(canv);
            if (IsDrawing && Math.Sqrt((StartPoint.X - EndPoint.X) * (StartPoint.X - EndPoint.X) + (StartPoint.Y - EndPoint.Y) * (StartPoint.Y - EndPoint.Y)) >= 10)
            {
                foreach (object ob in canv.Children)
                {
                    if (ob is Icon)
                    {
                        Icon ic = ob as Icon;
                        HitIconPoint = ic.Position;
                        for (int i = 0; i < dselect.SelectorPoints.Count - 2; i++)
                        {
                            if (IsInLine(dselect.SelectorPoints[i], dselect.SelectorPoints[i + 1], HitIconPoint, dselect.SelectorPoints[i+2]))
                                ic.CrossCount++;
                        }
                        if (dselect.SelectorPoints.Count >= 2)
                        {
                            if (IsInLine(dselect.SelectorPoints[dselect.SelectorPoints.Count - 2], dselect.SelectorPoints[dselect.SelectorPoints.Count - 1], HitIconPoint, dselect.SelectorPoints[0]))
                                ic.CrossCount++;
                            if (IsInLine(dselect.SelectorPoints[dselect.SelectorPoints.Count - 1], dselect.SelectorPoints[0], HitIconPoint, dselect.SelectorPoints[1]))
                                ic.CrossCount++;
                        }
                        if ((ic.CrossCount % 2) != 0)
                            ic.IsSelected = true;

                        ic.CrossCount = 0;
                        StartPoint = EndPoint;
                    }
                }
            }
        }

        //!—————————————————————————————————————
        private void CreatingLine(object sender, MouseEventArgs e)
        {
            if (!IsDrawing && CanCreateLine == CanCreateLineEnum.WaitForEndIcon)
            {
                Point mousept = new Point();
                mousept = e.GetPosition(canv);
                double d = Math.Sqrt(Math.Pow(mousept.X - CreateRL.X1, 2) + Math.Pow(mousept.Y - CreateRL.Y1, 2));
                if (d != 0)
                {
                    this.CreateRL.X2 = mousept.X - 5 * (mousept.X - CreateRL.X1) / d;
                    this.CreateRL.Y2 = mousept.Y - 5 * (mousept.Y - CreateRL.Y1) / d;
                }
                else 
                {
                    this.CreateRL.X2 = this.CreateRL.X1;
                    this.CreateRL.Y2 = this.CreateRL.Y1;
                }
            }
        }

        //!————————————————————————————————
        private void StartOrFinishCreateLine(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
            canv.Children.Remove(CreateRL);
            CanCreateLine = CanCreateLine == CanCreateLineEnum.WaitForEndIcon ? CanCreateLineEnum.Finish : CanCreateLineEnum.WaitForEndIcon;
            if (CanCreateLine == CanCreateLineEnum.WaitForEndIcon)
                {
                    CreateRL.Visibility = Visibility.Visible;
                    StartIcon = sender as Icon;
                    CreateRL.X1 = (StartIcon).Position.X;
                    CreateRL.Y1 = (StartIcon).Position.Y;
                    CreateRL.X2 = e.GetPosition(canv).X;
                    CreateRL.Y2 = e.GetPosition(canv).Y;
                    CreateRL.Stroke = Brushes.Orange;
                    CreateRL.Opacity = 0.7;
                    CreateRL.StrokeThickness = 2;
                    CreateRL.StrokeDashArray = new DoubleCollection(new double[] { 4, 2 });
                    canv.Children.Add(CreateRL);
                    Canvas.SetZIndex(CreateRL, Int32.MaxValue);
                }
                else if (CanCreateLine == CanCreateLineEnum.Finish)
                {
                    EndIcon = sender as Icon;
                    CreateRL.Visibility = Visibility.Hidden;
                    if (StartIcon != EndIcon)
                    {
                        canv.Children.Add(new RelationLine(StartIcon, EndIcon));
                        CanCreateLine = CanCreateLineEnum.NotBegin;
                        canv.Children.Remove(CreateRL);
                    }
                    else
                    {
                        CanCreateLine = CanCreateLineEnum.NotBegin;
                        canv.Children.Remove(CreateRL);
                    }
                    StartIcon = null;
                    EndIcon = null;
                }
            Console.WriteLine(CanCreateLine);
        }




        private bool IsInLine(Point pt1, Point pt2, Point pt, Point pt3)
        {
            if (pt1.Y == pt2.Y && pt1.Y == pt.Y)
            {
                if ((pt.X >= pt1.X || pt.X >= pt2.X) && pt3.Y != pt.Y) return true;
                else return false;
            }
            else if (pt.Y == pt2.Y && pt1.Y != pt2.Y)
            {
                if ((pt1.Y > pt.Y && pt3.Y < pt.Y) || (pt1.Y < pt.Y && pt3.Y > pt.Y))
                {
                    if (pt.X >= pt1.X + (pt.Y - pt1.Y) * (pt2.X - pt1.X) / (pt2.Y - pt1.Y)) return true;
                    else return false;
                }
                else return false;
            }
            else if (pt1.Y != pt2.Y && pt.Y < Math.Max(pt1.Y, pt2.Y) && pt.Y > Math.Min(pt1.Y, pt2.Y))
            {
                if (pt.X >= pt1.X + (pt.Y - pt1.Y) * (pt2.X - pt1.X) / (pt2.Y - pt1.Y)) return true;
                else return false;
            }
            else return false;
        }

        private void Window_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effects = DragDropEffects.Link;
            else
                if (e.Data.GetDataPresent(DataFormats.Text))
                    e.Effects = DragDropEffects.Copy;
        }

        private void Window_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                SourceDragOn(this, new Corona.TagPresent.SourceDragOnEventArgs(((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString(), Corona.TagPresent.SourceDragOnType.Link));
            else
                SourceDragOn(this, new Corona.TagPresent.SourceDragOnEventArgs(e.Data.GetData(DataFormats.Text).ToString(), Corona.TagPresent.SourceDragOnType.Text));
        }
        Icon icon3;
        Icon icon;
        Icon icon4;
        TagIcon tag;
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            canv.Children.Add(dselect);
            dselect.Height = 1500;
            dselect.Width = 2000;
            dselect.Visibility = Visibility.Hidden;
            canv.MouseLeftButtonDown += StartSelect;
            canv.MouseMove += OnSelecting;

            // -------------------------------------------------------------------------------------------------------Create line!!!!!!!
            canv.MouseMove += new MouseEventHandler(CreatingLine);
            canv.MouseLeftButtonUp += EndSelect;
            canv.MouseLeftButtonDown += new MouseButtonEventHandler(StopCreateRLine);
            
            icon4 = new Icon(64, 64, 600, 400);
            canv.Children.Add(new Icon());
            canv.Children.Add(new Icon(160, 160));
            canv.Children.Add(icon4);
            canv.Children.Add(new Icon("测试数据", @"F:\My Project\Corona\New\Corona\IconSource\icon02.png"));
            icon = new Icon(64, 64, 200, 200);
            canv.Children.Add(icon);
            //icon4.IsSelected = true;
            Icon icon2 = new Icon(64, 64, 500, 200);
            icon3 = new Icon("测试数据", @"F:\Artwork\Resourse\PNG\yahoo weather\Yahoo_Weather_002.png", 100, 100);
            icon3.SpecialButton.MouseDown += new MouseButtonEventHandler(SpecialButton_MouseDown);
            canv.Children.Add(icon2);
            canv.Children.Add(icon3);
            canv.Children.Add(new RelationLine(icon, icon2));
            canv.Children.Add(new RelationLine(icon, icon3));
            tag = new TagIcon("I'm a Tag!", @"F:\My Project\Corona\New\Corona\IconSource\icon01.png");
            canv.Children.Add(tag);
            canv.Children.Add(new RelationLine(icon, tag));
            icon3.BaseMouseClick += new Icon.BaseMouseClickHandler((obj) => { if (icon3.IsSelected) icon3.IsSelected = false; else icon3.IsSelected = true; });

            // -------------------------------------------------------------------------------------------------------Create line!!!!!!!
            icon.PreviewMouseRightButtonDown += new MouseButtonEventHandler(StartOrFinishCreateLine);
            icon4.PreviewMouseRightButtonDown += new MouseButtonEventHandler(StartOrFinishCreateLine);
            tag.MouseClick += new EventHandler<Corona.TagPresent.TagEventArgs>((obj, ev) => { if (tag.IsSelected) tag.IsSelected = false; else tag.IsSelected = true; });
            button1.Click += MoveIconsToCenter;
            tag.CloseButton.Click += new RoutedEventHandler(CloseButton_Click);
        }

        void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
        }


        void SpecialButton_MouseDown(object sender, MouseButtonEventArgs e)
        {
            canv.Children.Add(new Icon(64, 64));
        }
        private void StopCreateRLine(object sender, MouseButtonEventArgs e)
        {
            CanCreateLine = CanCreateLineEnum.NotBegin;
            Console.WriteLine(CanCreateLine.ToString());
            canv.Children.Remove(CreateRL);
            CreateRL.Visibility = Visibility.Hidden;
        }
        bool IsDrawing = false;
        DrawSelect dselect = new DrawSelect();
        Point StartPoint = new Point();
        Point EndPoint = new Point();
        Point HitIconPoint = new Point();
        PointCollection IconPointCollection = new PointCollection();
        Line CreateRL = new Line();
        Icon StartIcon;
        Icon EndIcon;
        CanCreateLineEnum CanCreateLine = CanCreateLineEnum.NotBegin;
        private void StartSelect(object sender, MouseButtonEventArgs e)
        {
            if (CanCreateLine == CanCreateLineEnum.NotBegin)
            {
                IsDrawing = true;
                Canvas.SetZIndex(dselect, Int32.MaxValue);
                foreach (Object ob in canv.Children)
                {
                    if (ob is Icon)
                    {
                        Icon ic = ob as Icon;
                        //  if (ic.toggle == false)
                        ic.IsSelected = false;
                        ic.CrossCount = 0;
                        //else ic.toggle = false;
                    }
                }
                dselect.ClearSelector();
                dselect.Visibility = Visibility.Visible;
                StartPoint = e.GetPosition(canv);
                dselect.InitialSelector(StartPoint);
            }
        }

        Point startingMPos = new Point();
        Point endingMPos = new Point();
        private bool posChanged = false;
        private bool? moving = null;
        private double dx;
        private double dy;
        private void CanvasDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            moving = false;
            canv.Cursor = Cursors.Arrow;
            startingMPos = e.GetPosition(canv); 
        }
        private void CanvasMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if ((moving != null) && (moving == false))
            {
                posChanged = true;
                canv.Cursor = Cursors.ScrollAll;
            }

            if (posChanged)
            {
                endingMPos = e.GetPosition(canv);

                dx = startingMPos.X - endingMPos.X;
                dy = startingMPos.Y - endingMPos.Y;

                double newPosY = canvasScroller.VerticalOffset + dy;
                double newPosX = canvasScroller.HorizontalOffset + dx;
                canvasScroller.ScrollToHorizontalOffset(newPosX);
                canvasScroller.ScrollToVerticalOffset(newPosY);
            }
        }

        private void CanvasUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            posChanged = false;
            moving = true;
            canv.Cursor = Cursors.Arrow;
        }






        private void MoveIconsToCenter(object sender, RoutedEventArgs e)
        {
            Icon[] list = new Icon[3];
            list[0] = icon;
            list[1] = icon3;
            list[2] = icon4;
            Random ran = new Random();
            for (int i = 0; i < 3; i++)
            {
                MoveToCenter(list[i], new Point(WindowCenterX +ran.Next(-200, 200), WindowCenterY + ran.Next(-200, 200)));
            }
            //MoveToCenter(icon, new Point(200, 300));
            //MoveToCenter(icon4, new Point(400, 600));
        }

        public double WindowCenterX
        {
            get 
            {
                Window1 parentWindow = Layout.Parent as Window1;
                return canvasScroller.HorizontalOffset + parentWindow.Width / 2; 
            }
        }
        public double WindowCenterY
        {
            get
            {
                Window1 parentWindow = Layout.Parent as Window1;
                return canvasScroller.VerticalOffset + parentWindow.Height / 2;
            }
        }
        private void MoveToCenter(Icon icon, Point position)
        {
            ScaleTransform myScaleTransform = new ScaleTransform();
            //this.RegisterName("MyAnimatedScaleTransform", myScaleTransform);
            myScaleTransform.ScaleX = 1;
            myScaleTransform.ScaleY = 1;
            icon.RenderTransform = myScaleTransform;
            Window1 parentWindow = Layout.Parent as Window1;
            //double endX = canvasScroller.HorizontalOffset + parentWindow.Width / 2;
            //double endY = canvasScroller.VerticalOffset + parentWindow.Height / 2;
            Storyboard movetocenter = new Storyboard();
            DoubleAnimationUsingKeyFrames moveX = new DoubleAnimationUsingKeyFrames();
            moveX.Duration = new Duration(TimeSpan.FromSeconds(1));
            moveX.KeyFrames.Add(new SplineDoubleKeyFrame(icon.Position.X, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
            moveX.KeyFrames.Add(new SplineDoubleKeyFrame(position.X, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(moveX.Duration.TimeSpan.TotalSeconds)), new KeySpline(0.5, 0, 0.5, 1)));
            DoubleAnimationUsingKeyFrames moveY = new DoubleAnimationUsingKeyFrames();
            moveY.Duration = new Duration(TimeSpan.FromSeconds(1));
            moveY.KeyFrames.Add(new SplineDoubleKeyFrame(icon.Position.Y, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
            moveY.KeyFrames.Add(new SplineDoubleKeyFrame(position.Y, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(moveY.Duration.TimeSpan.TotalSeconds)), new KeySpline(0.5, 0, 0.5, 1)));
            movetocenter.Children.Add(moveX);
            movetocenter.Children.Add(moveY);
            Storyboard.SetTarget(moveX, icon);
            Storyboard.SetTarget(moveY, icon);
            Storyboard.SetTargetProperty(moveX, new PropertyPath(Corona.Icon.XProperty));
            Storyboard.SetTargetProperty(moveY, new PropertyPath(Corona.Icon.YProperty));
            movetocenter.Begin(icon);
            Storyboard scale = new Storyboard();
            DoubleAnimationUsingKeyFrames scaleX = new DoubleAnimationUsingKeyFrames();
            scaleX.Duration = new Duration(TimeSpan.FromSeconds(1));
            scaleX.KeyFrames.Add(new SplineDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
            scaleX.KeyFrames.Add(new SplineDoubleKeyFrame(1.3, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5))));
            scaleX.KeyFrames.Add(new SplineDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(scaleX.Duration.TimeSpan.TotalSeconds))));
            DoubleAnimationUsingKeyFrames scaleY = new DoubleAnimationUsingKeyFrames();
            scaleY.Duration = new Duration(TimeSpan.FromSeconds(1));
            scaleY.KeyFrames.Add(new SplineDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
            scaleY.KeyFrames.Add(new SplineDoubleKeyFrame(1.3, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5))));
            scaleY.KeyFrames.Add(new SplineDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(scaleY.Duration.TimeSpan.TotalSeconds))));
            scale.Children.Add(scaleX);
            scale.Children.Add(scaleY);
            Storyboard.SetTarget(scaleX, myScaleTransform);
            Storyboard.SetTarget(scaleY, myScaleTransform);
            Storyboard.SetTargetProperty(scaleX, new PropertyPath(ScaleTransform.ScaleXProperty));
            Storyboard.SetTargetProperty(scaleY, new PropertyPath(ScaleTransform.ScaleYProperty));
            scale.Begin(icon);
        }
    }

    //！———————————————————————————————————————————————
    public enum CanCreateLineEnum
    {
        WaitForEndIcon,
        NotBegin,
        Finish
    }
}
